#region Imported Namespaces


using System.Windows.Input;

using WtfManager.Framework;


#endregion


namespace WtfManager.UIManager.Commands
{
  ///<summary>
  /// An extension of <see cref="CommandBinding"/>
  ///</summary>
  public class WtfCommandBinding: CommandBinding
  {
    #region Constructors/Finalizers


    ///<summary>
    /// WtfCommandBinding constructor.
    ///</summary>
    public WtfCommandBinding()
    {
      SetHandlers();
    }


    ///<summary>
    /// WtfCommandBinding constructor.
    ///</summary>
    public WtfCommandBinding(ICommand command)
      : base(command)
    {
      SetHandlers();
    }


    #endregion


    #region Properties/Indexers


    ///<summary>
    /// Gets or sets command parameters.
    ///</summary>
    public object DefaultParameters
    {
      get;
      set;
    }


    #endregion


    #region Methods


    private void SetHandlers()
    {
      CanExecute += WtfCommandBindingCanExecute;
      Executed += WtfCommandBindingExecuted;
    }


    private void WtfCommandBindingExecuted(object sender, ExecutedRoutedEventArgs e)
    {
      CommandsService service = GetCommandsService();

      if (service == null)
      {
        return;
      }

      object parameter = GetCommandParameter(sender, e.Parameter);

      service.CommandExecuted(sender, e, parameter);
    }


    private static CommandsService GetCommandsService()
    {
      var service = (CommandsService)WtfFramework.Instance.Services[typeof(CommandsService)];

      return service.State == FrameworkComponentState.Initialized ? service : null;
    }


    private void WtfCommandBindingCanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
      var service = GetCommandsService();

      if (service == null)
      {
        return;
      }

      object parameter = GetCommandParameter(sender, e.Parameter);

      service.CanExecuteCommand(sender, e, parameter);
    }


    private object GetCommandParameter(object sender, object explicitParameter)
    {
      object parameter = DefaultParameters;

      if (explicitParameter != null)
      {
        parameter = explicitParameter;
      }

      if (parameter is WtfCommandParameters)
      {
        var commandParameters = (WtfCommandParameters)parameter;

        commandParameters.CommandTarget = sender;
      }

      return parameter;
    }


    #endregion
  }
}